package at.ac.lbg.media.vis.client.theme.manager
{
	
	import at.ac.lbg.media.vis.client.theme.operator.CustomLabeler;
	import at.ac.lbg.media.vis.client.theme.render.IArtworkRenderer;
	import at.ac.lbg.media.vis.client.theme.view.Artwork;
	import at.ac.lbg.media.vis.client.theme.view.ArtworkStack;
	
	import flare.display.TextSprite;
	import flare.util.Colors;
	import flare.vis.Visualization;
	import flare.vis.controls.ClickControl;
	import flare.vis.controls.HoverControl;
	import flare.vis.data.Data;
	import flare.vis.data.DataSprite;
	import flare.vis.events.SelectionEvent;
	import flare.vis.operator.layout.AxisLayout;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.text.TextFormat;
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	import mx.controls.List;
	import mx.core.Application;
	
	public class LandscapeManager {
		
		public static var LABELER:String = "labeler";
		public var artworkRenderer:IArtworkRenderer;
		
		private var info1:TextSprite;
		
		public function LandscapeManager() {
			// quasi dependency injection with spring actionscript
			artworkRenderer = Application.application.applicationContext.getObject("artworkRenderer");
		}
		
		public function initLandscape(viz:Visualization, data:ArrayCollection):void {//, awdC:ArrayCollection):void {
			var catDict:Dictionary = Application.application.catDict;
			var legend:List = Application.application.legend;

			viz.data = convertData(data);
			
			// define the visual encodings
			viz.data.nodes.setProperties({
				fillColor: 0x018888ff, // transparent fill to catch mouse hits
				lineWidth: 2
			});
			
			// define x and y fields from which vis should operate
			var field1:String = "origX";
			var field2:String = "origY";
			var layout:AxisLayout = new AxisLayout(field1, field2);
			viz.operators.add(layout);
			viz.xyAxes.xAxis.fixLabelOverlap = false; // keep overlapping labels
			viz.axes.alpha = 0;
			
			// Labels for each artwork
//			var labeler:CustomLabeler = new CustomLabeler("title", null, new TextFormat("Arial", "11", "0x336633"), function(item:Artwork):Boolean{ return item.stackCount < 2 }, CustomLabeler.CHILD);
			var labeler:CustomLabeler = new CustomLabeler("title", null, new TextFormat("Arial", "11", "0x336633"), function(item:Artwork):Boolean{ return item.stackCount < 2 || item.stack }, CustomLabeler.CHILD);			
			//var labeler:Labeler = new Labeler("title", null, new TextFormat("Arial", "13", "0x336633"), function(item:Artwork):Boolean{ return item.stackCount < 2 }, Labeler.CHILD);
			
			//for debugging
			//var labeler:CustomLabeler = new CustomLabeler("year", null, new TextFormat("Arial", "11", "0x336633"), function(item:Artwork):Boolean{ return item.stackCount < 2 }, CustomLabeler.CHILD);
			
			labeler.xOffset = 15;
			labeler.yOffset = 0;
			labeler.horizontalAnchor = TextSprite.LEFT;
			labeler.textMode = TextSprite.DEVICE;
			//test
			viz.operators.add(labeler);
			
			//test textSprite wird angezeigt und führt methode aus
//			var testbox:Sprite = new Sprite();
//						testbox.name = "testbox";
//						var yOffset:int = 0;
//						
//			var test:TextSprite = new TextSprite();
//						test.text = "test";
//						test.textField.background = true;
//						test.textField.backgroundColor = Colors.rgba(255, 255, 255);
//						test.scaleX = 0.7;
//						test.scaleY = 0.7;
//						test.y = 10;
//						test.textFormat = new TextFormat("Arial", "21", "0x336633");
//						test.buttonMode = true;
//						test.addEventListener(MouseEvent.MOUSE_OVER, onStackClick);
//						test.textMode = TextSprite.DEVICE;
//						testbox.addChild(test);
//				viz.addChild(testbox);								
			//testend
			
			// add mouse over
			var hc:HoverControl = new HoverControl(
				DataSprite, 
				HoverControl.MOVE_TO_FRONT, 
				//roll in
				function(e:SelectionEvent):void {
					//e.item.filters = [new GlowFilter(0xE6821E, 0.8, 4, 4, 2, 1, true, false)];
					var aw:Artwork = e.item as Artwork;
					aw.origHeight = aw.height;
					aw.origWidth = aw.width;
					aw.scaleX = 1.5;
					aw.scaleY = 1.5;

					if (aw.stack) {
						// TODO StackDetails: das ist die einzige lösung die halbwegs geklappt hat.
						// click wird noch vom ClickControl auf das aw abgefangen.
//						var box:Sprite = new Sprite();
//						box.name = "box";
//						var yOffset:int = 0;
//						for each (var stackedAw:Artwork in aw.stack.artworks) {
//							var stLabel:TextSprite = new TextSprite();
//							stLabel.textFormat = new TextFormat("Arial", "11", "0x336633");
//							stLabel.textField.background = true;
//							stLabel.textField.backgroundColor = Colors.rgba(255, 255, 255);
//							stLabel.scaleX = 0.7;
//							stLabel.scaleY = 0.7;
//							stLabel.y = yOffset * 10;
//							stLabel.text = stackedAw.title;
//							stLabel.addEventListener(MouseEvent.CLICK, onStackClick);
//							box.addChild(stLabel);
//							yOffset++;
						var box:Sprite = new Sprite();
						box.name = "box";
						var yOffset:int = 0;
						// add first artwork label
						var stFirstLabel:TextSprite = new TextSprite();
						stFirstLabel.text = aw.title;
						stFirstLabel.textField.background = true;
						stFirstLabel.textField.backgroundColor = Colors.rgba(255, 255, 255);
						stFirstLabel.scaleX = 0.7;
						stFirstLabel.scaleY = 0.7;
						stFirstLabel.textFormat = new TextFormat("Arial", "11", "0x336633");
						stFirstLabel.buttonMode = true;
						stFirstLabel.addEventListener(MouseEvent.MOUSE_OVER, onStackClick);
						stFirstLabel.textMode = TextSprite.DEVICE;
						box.addChild(stFirstLabel);
						yOffset++;
						
	
						for each (var stackedAw:Artwork in aw.stack.artworks) {
							var stLabel:TextSprite = new TextSprite();
							stLabel.text = stackedAw.title;
							stLabel.textField.background = true;
							stLabel.textField.backgroundColor = Colors.rgba(255, 255, 255);
							stLabel.scaleX = 0.7;
							stLabel.scaleY = 0.7;
							stLabel.y = yOffset * 10;
							stLabel.textFormat = new TextFormat("Arial", "11", "0x336633");
							stLabel.buttonMode = true;
							stLabel.addEventListener(MouseEvent.MOUSE_OVER, onStackClick);
							stLabel.textMode = TextSprite.DEVICE;
							box.addChild(stLabel);
							yOffset++;
						}
						aw.addChild(box);
						//box.addEventListener(MouseEvent.CLICK, onStackClick);

											
//						var label:TextSprite;
//						label = new TextSprite(aw.stack.label);
//						label.name = "awlabel";
//						label.textField.background = true;
//						label.textField.backgroundColor = Colors.rgba(255, 255, 255);
//						label.x = 16;
//						label.y = -1;
//						label.verticalAnchor = TextSprite.CENTER;
//						label.textFormat = new TextFormat("Arial", "9", "0x336633");
//						label.textMode = TextSprite.DEVICE;
//						aw.addChild(label);
						


						// hide original label
						if (aw.numChildren > 0) {
							aw.getChildAt(0).alpha = 0;
						}
					} else if (!Application.application.showLabels) {
						var label:TextSprite;
						label = new TextSprite(aw.title);
						label.name = "awlabel";
						label.x = 16;
						label.y = -1;
						label.verticalAnchor = TextSprite.CENTER;
						label.textFormat = new TextFormat("Arial", "11", "0x336633");
						label.textMode = TextSprite.DEVICE;
						label.textField.filters = [new GlowFilter(0xFFFFFF, 1, 4, 4, 200, 1)];
						aw.addChild(label);
					}
					
					
					Application.application.categoryManager.handleSelectedCats(aw.categoryIds);
				},	
				//roll out			
				function(e:SelectionEvent):void {
					//e.item.filters = null;
					Application.application.stackList.visible = false;
					var aw:Artwork = e.item as Artwork;
					var sp:TextSprite = aw.getChildByName("awlabel");
					if (sp != null) {
						e.item.removeChild(sp);
					}
					if (aw.stack) {

						var b:Sprite = aw.getChildByName("box");
						if (b != null) {
							aw.removeChild(b);
						}
						if (e.item.numChildren > 0) {
							if (Application.application.showLabels) {
								e.item.getChildAt(0).alpha = 1;
							}
						}
					}

					var details:TextSprite = aw.getChildByName("details");
					if (details != null) {
						details.visible = false;
						e.item.removeChild(details);
					}
					//Application.application.details.visible = false;
					Application.application.categoryManager.handleSelectedCats(null);
					aw.scaleX = 1.0;
					aw.scaleY = 1.0;

				}
			);
			viz.controls.add(hc);
			
			//hover contorl für einzelne stacks geht nich
//			var hcSt:HoverControl = new HoverControl(
//				TextSprite, 
//				HoverControl.MOVE_TO_FRONT, 
//				//roll in
//				function(e:SelectionEvent):void {
//					var awSt:ArtworkStack = e.item as ArtworkStack;
//					awSt.scaleX = 5.5;
//					awSt.scaleY = 5.5;
//				},
//				function(e:SelectionEvent):void {
//					var awSt:ArtworkStack = e.item as ArtworkStack;
//					awSt.scaleX = 1.0;
//					awSt.scaleY = 1.0;
//				});
//			viz.controls.add(hcSt);
			
			var dm:DetailsManager = Application.application.detailsManager;
			// TODO StackDetails: statt DataSprite eine filter-function (keine ahnung wie es genau geht) die artwork.stack abfragt,
			// um diese clickcontrol von den Stacks zu nehmen.
			//filter funktioniert, nicht bei klick in landscape weil "rect" nicht in "artwork" umgewandelt werden kann ??
			//auch wenn beide auskomentiert sind reagiert der stack nicht auf den event, test event oben funktioniert
//			var cc:ClickControl = new ClickControl(
//				//function(item:Artwork):Boolean{ return item.stackCount < 2},
//				DataSprite,
//				1); //2 für doppelklick	
//			cc.addEventListener(SelectionEvent.SELECT, dm.onSingleClick);
//			viz.controls.add(cc);
//
//			var ccSt:ClickControl = new ClickControl(
//				function(item:Artwork):Boolean{ return item.stackCount > 1 },
//				//DataSprite,
//				1);	
//			ccSt.addEventListener(SelectionEvent.SELECT, onStackClick);
//			viz.controls.add(ccSt);
			var ccSt:ClickControl = new ClickControl(
				DataSprite,
				1);	
			ccSt.addEventListener(SelectionEvent.SELECT, dm.onSingleClick);
			viz.controls.add(ccSt);

		}
		
		//mousevent for MouseEvent
		private function onStackClick(evt:MouseEvent):void {
		//SelectionEvent for ClickControl
//		private function onStackClick(evt:SelectionEvent):void {

//			var text:TextSprite = event.target as TextSprite;
//			text.text = "Juhuuu";

			//var awSt:ArtworkStack = evt.item as ArtworkStack;			
			//ausgabe im debug modus
			trace("onStackClick");
		}
		
		public function convertData(artworks:ArrayCollection):Data {
			var stacks:ArrayCollection = new ArrayCollection();
			
			// built the stacks
			for each(var aw:Artwork in artworks) {
				var stackExists:Boolean = false;
								
				// stackCount is computed on the server and indicates the amount
				// of artworks on a stack. we do only draw a stack once and skip all
				// the other artworks on this stack.
				if (aw.stackCount > 1) {
					var c:String = aw.origX + "#" + aw.origY;
					// is this artwork in a stack that has already been created?
					// if yes: just add the label.
					for each (var st:ArtworkStack in stacks) {
						if (st.coords == c) { // has same position -> put it in the stack
							st.artworks.addItem(aw);
							stackExists = true;
							if (aw.nica) {
								st.hasNica = true;
							}
							break;
						}
					}
					if (!stackExists) {
						// we built a new stack...
						var newStack:ArtworkStack = new ArtworkStack();
						newStack.coords = c;
						if (aw.nica) {
							newStack.hasNica = true;
						}
						newStack.artworks.addItem(aw);
						stacks.addItem(newStack);
					}
				}
			}
				
				
			// put all Nicas on top of their stacks
			// also rebuild the stack label in this case
			for each (var sta:ArtworkStack in stacks) {
				if (sta.hasNica) {
					for each (var work:Artwork in sta.artworks) {
						if (work.nica) {
							sta.artworks.removeItemAt(sta.artworks.getItemIndex(work));
							work.stack = sta;
							sta.label = work.title;
						} 
					}
				} else {
					var firstAw:Artwork = sta.artworks.getItemAt(0) as Artwork;
					sta.artworks.removeItemAt(0);
					firstAw.stack = sta;
					sta.label = firstAw.title;
				}
			}
			
			// build labels
			for each (var st:ArtworkStack in stacks) {
				for each (var aw3:Artwork in st.artworks) {
					st.label += "\n" + aw3.title;
				}
			}
			var data:Data = new Data();
			for each(var aw2:Artwork in artworks) {

				aw2.renderer = artworkRenderer;
				aw2.mouseChildren = false;
				aw2.buttonMode = true;
				data.addNode(aw2);
				
			}
			return data;
		}

	}
}